3 Password reset broken logic
Capturamos la request de password reset con nuestra cuenta manipulamos el campo user hacia carlos y enviamos la request
POST /forgot-password?temp-forgot-password-token=15148sy5dtxg4v8aofyz0uxcti2n240k HTTP/2
temp-forgot-password-token=15148sy5dtxg4v8aofyz0uxcti2n240k&username=******wiener******&new-password-1=wiener&new-password-2=wiener
the username field can be modified to 'carlos'
temp-forgot-password-token=15148sy5dtxg4v8aofyz0uxcti2n240k&username=******carlos******&new-password-1=wiener&new-password-2=wiener
La vulnerabilidad ocurre porque el backend no vincula el temp-forgot-password-token con el usuario correcto en el servidor y confía en el parámetro username enviado por el cliente. Esto permite reutilizar un token legítimo generado para la cuenta propia y modificar el campo username a carlos, logrando resetear su contraseña. La lógica rota consiste en validar únicamente que el token sea válido, pero no que pertenezca al mismo usuario cuyo password se está modificando. Es un caso de Broken Access Control y Improper Token Binding según OWASP.
# Implementación vulnerable
# POST /forgot-password (reset final)
if valid_token(request.temp_token):
user = request.username # ❌ Confía en input del cliente
if request.new_password_1 == request.new_password_2:
update_password(user, request.new_password_1)
invalidate_token(request.temp_token)
# Implementación segura
# Token debe estar ligado al usuario en servidor
token_data = get_token_data(request.temp_token)
if token_data and token_data.user == request.username:
if request.new_password_1 == request.new_password_2:
update_password(token_data.user, request.new_password_1)
invalidate_token(request.temp_token)
else:
deny_request()